package com.goldgov.kduck.config;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.*;
import org.springframework.security.access.ConfigAttribute;
import org.springframework.security.web.FilterInvocation;
import org.springframework.security.web.access.intercept.FilterInvocationSecurityMetadataSource;
import org.springframework.security.web.util.matcher.RequestMatcher;
import org.springframework.util.StringUtils;
import org.springframework.web.client.RestTemplate;

import javax.servlet.http.HttpServletRequest;
import java.util.*;

public class CustomSecurityMetadataSource implements FilterInvocationSecurityMetadataSource {
    private Logger log = LoggerFactory.getLogger(this.getClass());
    private FilterInvocationSecurityMetadataSource hardCodedSecurityMetadataSource;
    private RestTemplate restTemplate;
    private GatewayProperties gatewayProperties;
    public CustomSecurityMetadataSource(GatewayProperties gatewayProperties,RestTemplate restTemplate, FilterInvocationSecurityMetadataSource expressionBasedFilterInvocationSecurityMetadataSource) {
        this.hardCodedSecurityMetadataSource = expressionBasedFilterInvocationSecurityMetadataSource;
        this.restTemplate = restTemplate;
        this.gatewayProperties = gatewayProperties;
    }
    private Map<RequestMatcher, Collection<ConfigAttribute>> resourceMap = new HashMap<>(32);

    @Override
    public Collection<ConfigAttribute> getAttributes(Object object) throws IllegalArgumentException {
        FilterInvocation filterInvocation = (FilterInvocation) object;
        HttpServletRequest request = filterInvocation.getHttpRequest();
        String requestUrl = filterInvocation.getRequestUrl();
        if (resourceMap == null || resourceMap.size() == 0) {
            loadResource(request);
        }
        for (Map.Entry<RequestMatcher, Collection<ConfigAttribute>> entry : resourceMap
                .entrySet()) {
            if (entry.getKey().matches(request)) {
                log.info("【" + requestUrl + "】匹配到DB权限列表");
                return entry.getValue();
            }
        }
        log.info("【" + requestUrl + "】不在DB权限列表当中,尝试匹配代码中的权限配置...");

///        return null; //默认白名单通过

        //  返回代码定义的默认配置(authenticated、permitAll等)
        Collection<ConfigAttribute> configAttributes = hardCodedSecurityMetadataSource.getAttributes(object);
        if (configAttributes == null || configAttributes.size() == 0) {
            log.info("【" + requestUrl + "】不在代码中的权限配置");
        } else {
            log.info("【" + requestUrl + "】匹配到代码中硬编码的配置或默认配置");
        }
        return configAttributes;
    }

    private void loadResource(HttpServletRequest request) {
//        http://autherserver.sso.com:8080/authorserver/oauth/token?grant_type=client_credentials&client_id=baiduClient&client_secret=tgb.258
        String url = gatewayProperties.getResourceUrl();
        HttpHeaders headers = new HttpHeaders();
        String authorization = request.getHeader("authorization");
        if (!StringUtils.hasText(authorization)){
            log.error("未无获取token值，无法获取系统资源。");
            return;
        }else {
            String token = authorization.substring(7, authorization.length());
            headers.setBearerAuth(token);
        }
        headers.setAccept(Arrays.asList(MediaType.APPLICATION_JSON));
        HttpEntity<String> entity = new HttpEntity<String>("parameters", headers);
        ResponseEntity<Map> exchange = restTemplate.exchange(url, HttpMethod.GET, entity, Map.class);
        System.out.println(exchange.getBody());
        Map body = exchange.getBody();
        ArrayList<Map> data = (ArrayList<Map>) body.get("data");
        for (int i = 0; i < data.size(); i++) {
            Map map = data.get(i);
            ArrayList children = (ArrayList) map.get("children");
            //TODO operateId为key  operatePath,method 为值
        }
    }

    @Override
    public Collection<ConfigAttribute> getAllConfigAttributes() {
        Set<ConfigAttribute> allAttributes = new HashSet<>();

        for (Map.Entry<RequestMatcher, Collection<ConfigAttribute>> entry : resourceMap
                .entrySet()) {
            allAttributes.addAll(entry.getValue());
        }
        return allAttributes;
    }

    @Override
    public boolean supports(Class<?> aClass) {
        return true;
    }
}
